package cn.edu.cqie.utils;

import java.security.Key;
import java.util.Date;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.edu.cqie.enums.RespToAppEnum;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

/**
 * @author potato
 * 
 *         就是一个token生成工具
 */
public class JwtTokenUtil {
	private static Logger log = LoggerFactory.getLogger(JwtTokenUtil.class);
	public static final String AUTH_HEADER_KEY = "Authorization";
	public static final String TOKEN_PREFIX = "Bearer ";

	/**
	 * 解析jwt
	 * 
	 * @param jsonWebToken
	 * @param base64Security
	 * @return
	 */
	public static Claims parseJWT(String jsonWebToken, String base64Security) {
		try {
			Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))
					.parseClaimsJws(jsonWebToken).getBody();
			return claims;
		} catch (ExpiredJwtException eje) {
			log.error("===== Token过期 =====", eje);
			throw new BizException(RespToAppEnum.TOKEN_EXPIRED);
		} catch (Exception e) {
			log.error("===== token解析异常 =====", e);
			throw new BizException(RespToAppEnum.TOKEN_ERROR);
		}
	}

	/**
	 * @param duration
	 * @param role
	 * @param userId
	 * @return
	 */
	public static String createJWT(int duration, String role, String userId) {
		try {
			// 使用HS256加密算法
			SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
			long nowMillis = System.currentTimeMillis();
			Date now = new Date(nowMillis);
			// 生成签名密钥
			byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(CommonConstant.BASE64SECRET);
			Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
			// 添加构成JWT的参数,没有一个重要的
			JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
					// 可以将基本不重要的对象信息放到claims
					.claim("role", role).claim("userId", userId).setSubject("gungun") // 代表这个JWT的主体，即它的所有人
					.setIssuer(CommonConstant.ISSUER) // 代表这个JWT的签发主体；
					.setIssuedAt(new Date()) // 是一个时间戳，代表这个JWT的签发时间；
					.setAudience("restapiuser") // 代表这个JWT的接收对象；
					.signWith(signatureAlgorithm, signingKey);
			// 添加Token过期时间
			int TTLMillis = duration;
			if (TTLMillis >= 0) {
				long expMillis = nowMillis + TTLMillis;
				Date exp = new Date(expMillis);
				builder.setExpiration(exp) // 是一个时间戳，代表这个JWT的过期时间；
						.setNotBefore(now); // 是一个时间戳，代表这个JWT生效的开始时间，意味着在这个时间之前验证JWT是会失败的
			}
			// 生成JWT
			return builder.compact();
		} catch (Exception e) {
			log.error("签名失败", e);
			throw new BizException(RespToAppEnum.SIGNATURE_ERROR);
		}
	}

	/**
	 * 从token中获取用户名
	 * 
	 * @param token
	 * @param base64Security
	 * @return
	 */
	public static String getUsername(String token, String base64Security) {
		return parseJWT(token, base64Security).getSubject();
	}

	/**
	 * 是否已过期
	 * 
	 * @param token
	 * @param base64Security
	 * @return
	 */
	public static boolean isExpiration(String token, String base64Security) {
		return parseJWT(token, base64Security).getExpiration().before(new Date());
	}
}
